﻿using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Collections.ObjectModel;



namespace Tfs_analyzer
  {
  class ValidationXLSWriter
    {
    //should be improoved based on team members
    private static bool IsReviewerOk(string name)
      {
      if (name.Trim().Length < 5)
        return false;
      return true;
      }

    private static HashSet<string> GetUniqueUserNames(ValidationSummary i_summary)
      {
      HashSet<string> result = new HashSet<string>();
      
      foreach (var res in i_summary.m_validation_info)
        {
        result.Add(res.OwnerDisplayName.ToString());
        }

      return result;
      }

    private static List<Changeset> GetChangesetsOnly(ValidationSummary i_summary)
      {
      List<Changeset> result = new List<Changeset>();
      foreach (var res in i_summary.m_validation_info)
        {
        result.Add(res);
        }

      return result;
      }

    private static HashSet<string> GetWeeksStartsDates(ValidationSummary i_summary)
      {
      HashSet<string> result = new  HashSet<string>();
      foreach (var res in i_summary.m_validation_info)
        {
        result.Add(res.CreationDate.AddDays(DayOfWeek.Monday - res.CreationDate.DayOfWeek).ToShortDateString());
        }

      return result;
      }


    public static int WriteReviewStatistics(Microsoft.Office.Interop.Excel._Worksheet io_work_sheet, int i_starting_index, Collection<ValidationSummary> i_validation_datas)
      {

      int project_name_row = i_starting_index;
      int working_row = project_name_row + 1;

      int row_name_col = 1;
      int name_col = 2;
      int column = 3; 

      foreach (ValidationSummary summary in i_validation_datas)
        {
        var users = GetUniqueUserNames(summary);
        var periods = GetWeeksStartsDates(summary);
        var changesets = GetChangesetsOnly(summary);

        io_work_sheet.Cells[project_name_row, name_col] = summary.project;
        io_work_sheet.Cells[project_name_row, row_name_col] = "Project";
        int col = column;
        foreach (string name in users)
          {
          int row = working_row;
          io_work_sheet.Cells[project_name_row, col] = name;

          foreach (string period in periods)
            {
            //let's get all changesets from this period:
            var changesets_during_period =
              (from entry in changesets
               where entry.CreationDate.AddDays(DayOfWeek.Monday - entry.CreationDate.DayOfWeek).ToShortDateString() == period
               select entry).ToList();

            var result_total_changesets =
              (from entry in changesets_during_period
               where entry.OwnerDisplayName.ToString() == name
               select entry).ToList();

            var result_with_valid_reviewer =
               (from entry in changesets_during_period
                where entry.OwnerDisplayName.ToString() == name &&
                IsReviewerOk(entry.CheckinNote.Values.Length > 0 ? entry.CheckinNote.Values[0].Value : "no")
                select entry).ToList();

            io_work_sheet.Cells[row, col] = result_total_changesets.Count > 0 ? ((double)result_with_valid_reviewer.Count / (double)result_total_changesets.Count) : 0;
            io_work_sheet.Cells[row, name_col] = period;
            row++;
            }
          col++;
          }
        working_row += periods.Count;
        project_name_row = working_row + 1;
        working_row = project_name_row + 1;
        }

      return working_row;
      }

    public static int WriteChangesetsCountStatistics(Microsoft.Office.Interop.Excel._Worksheet io_work_sheet, int i_starting_index, Collection<ValidationSummary> i_validation_datas)
      {

      int project_name_row = i_starting_index;
      int working_row = project_name_row + 1;

      int row_name_col = 1;
      int name_col = 2;
      int column = 3;

      foreach (ValidationSummary summary in i_validation_datas)
        {
        var users = GetUniqueUserNames(summary);
        var periods = GetWeeksStartsDates(summary);
        var changesets = GetChangesetsOnly(summary);

        io_work_sheet.Cells[project_name_row, name_col] = summary.project;
        io_work_sheet.Cells[project_name_row, row_name_col] = "Project";
        int col = column;
        foreach (string name in users)
          {
          int row = working_row;
          io_work_sheet.Cells[project_name_row, col] = name;

          foreach (string period in periods)
            {
            //let's get all changesets from this period:
            var changesets_during_period =
              (from entry in changesets
               where entry.CreationDate.AddDays(DayOfWeek.Monday - entry.CreationDate.DayOfWeek).ToShortDateString() == period
               select entry).ToList();

            var result_total_changesets =
              (from entry in changesets_during_period
               where entry.OwnerDisplayName.ToString() == name
               select entry).ToList();

            io_work_sheet.Cells[row, col] = result_total_changesets.Count; ;
            io_work_sheet.Cells[row, name_col] = period;
            row++;
            }
          col++;
          }
        working_row += periods.Count;
        project_name_row = working_row + 1;
        working_row = project_name_row + 1;
        }

      return working_row;
      }



    public static int WriteAttachedItemsCountStatistics(Microsoft.Office.Interop.Excel._Worksheet io_work_sheet, int i_starting_index, Collection<ValidationSummary> i_validation_datas)
      {

      int project_name_row = i_starting_index;
      int working_row = project_name_row + 1;

      int row_name_col = 1;
      int name_col = 2;
      int column = 3;

      foreach (ValidationSummary summary in i_validation_datas)
        {
        var users = GetUniqueUserNames(summary);
        var periods = GetWeeksStartsDates(summary);
        var changesets = GetChangesetsOnly(summary);

        io_work_sheet.Cells[project_name_row, name_col] = summary.project;
        io_work_sheet.Cells[project_name_row, row_name_col] = "Project";
        int col = column;
        foreach (string name in users)
          {
          int row = working_row;
          io_work_sheet.Cells[project_name_row, col] = name;

          foreach (string period in periods)
            {
            //let's get all changesets from this period:
            var changesets_during_period =
              (from entry in changesets
               where entry.CreationDate.AddDays(DayOfWeek.Monday - entry.CreationDate.DayOfWeek).ToShortDateString() == period
               select entry).ToList();

            var result_total_changesets_by_user_in_period =
              (from entry in changesets_during_period
               where entry.OwnerDisplayName.ToString() == name
               select entry).ToList();

            int tasks = 0;
            foreach (Changeset changeset in result_total_changesets_by_user_in_period)
              foreach (AssociatedWorkItemInfo wi in changeset.AssociatedWorkItems)
              {
              if (wi.WorkItemType == "Task")
                tasks++;
              }

            io_work_sheet.Cells[row, col] = result_total_changesets_by_user_in_period.Count > 0 ? ((double)tasks / (double)result_total_changesets_by_user_in_period.Count) : 0;
            io_work_sheet.Cells[row, name_col] = period;
            row++;
            }
          col++;
          }
        working_row += periods.Count;
        project_name_row = working_row + 1;
        working_row = project_name_row + 1;
        }

      return working_row + 1;
      }


    public static void ExportToExcel(Collection<ValidationSummary> i_validation_datas, string i_path, object format)
      {
      if (i_validation_datas == null || i_path == null)
        throw new Exception("Empty input data for export");

      // load excel, and create a new workbook
      Microsoft.Office.Interop.Excel.Application excel_app = new Microsoft.Office.Interop.Excel.Application();
      excel_app.Workbooks.Add();

      // single work_sheet
      Microsoft.Office.Interop.Excel._Worksheet work_sheet = excel_app.ActiveSheet;

      //adding headers
      for (int i = 0; i < m_headers.Length; i++)
        {
        work_sheet.Cells[1, (i + 1)] = m_headers[i];
        }

      int row = 2;
      foreach (ValidationSummary summary in i_validation_datas)
        {
        foreach (var res in summary.m_validation_info)
          {
          work_sheet.Cells[row, 1] = res.ChangesetId.ToString();
          work_sheet.Cells[row, 2] = summary.project;//check?
          work_sheet.Cells[row, 3] = res.CreationDate.ToShortDateString();
          work_sheet.Cells[row, 4] = res.CreationDate.AddDays(DayOfWeek.Monday - res.CreationDate.DayOfWeek).ToShortDateString();
          work_sheet.Cells[row, 5] = res.OwnerDisplayName.ToString().Replace("MATONE\\", "");
          work_sheet.Cells[row, 6] = res.Comment.Replace("***NO_CI***", "");

          string work_items = "";
          int bugs = 0, tasks = 0;
          foreach (AssociatedWorkItemInfo wi in res.AssociatedWorkItems)
            {
            work_items += "#" + wi.Id.ToString() + "; ";
            if (wi.WorkItemType == "Task")
              tasks++;
            else
              bugs++;
            }
          work_sheet.Cells[row, 7] = work_items;
          work_sheet.Cells[row, 8] = bugs;
          work_sheet.Cells[row, 9] = tasks;

          work_sheet.Cells[row, 10] = "n/a";
          string reviewer = res.CheckinNote.Values.Length > 0 ? res.CheckinNote.Values[0].Value : "no";
          work_sheet.Cells[row, 11] = reviewer;
          work_sheet.Cells[row, 12] = IsReviewerOk(reviewer) ? "yes" : "no";
          row++;
          }
        }
      work_sheet.Cells[++row, 1] = "Review statistics: ratio between total changesets count with valid reviewer and  total count of changeset during period";
      row = WriteReviewStatistics(work_sheet, row + 2, i_validation_datas);
      work_sheet.Cells[++row, 1] = "Changeset count statistics during period";
      row = WriteChangesetsCountStatistics(work_sheet, row + 2, i_validation_datas);
      work_sheet.Cells[++row, 1] = "Work items per changeset statistics during period";
      row = WriteAttachedItemsCountStatistics(work_sheet, row + 2, i_validation_datas);
      String path_to_file = i_path + ".xlsx";
      if (File.Exists(path_to_file))
        {
        File.Delete(path_to_file);
        }

      work_sheet.SaveAs(i_path, format);
      excel_app.Quit();

      }
    private static string[] m_headers = new string[] { "ID", "Project", "Date", "Week start day", "User", "Title", "Related Work Items", "Bugs count", "Tasks count", "Changes", "Code Reviewer", "Is Reviewer valid" };
                                                      // 1        2        3       4               5         6         7                      8            9             10        11                     12
    }
  }
